-- Winter Anathema (c) v.v.balashoff
local Color = require('libs/colorlibrary/colorlibrary')
local Domain = require('leviathan/ECS/Domain')
local Entity = require('leviathan/ECS/Entity')
local i18n = require('libs/i18n')
local Log = require('leviathan/Log')
local MouseClickComponent = require('leviathan/ECS/UI/Components/MouseClickComponent')
local MouseHoverComponent = require('leviathan/ECS/UI/Components/MouseHoverComponent')
local TextComponent = require('leviathan/ECS/UI/Components/TextComponent')
local TextureComponent = require('leviathan/ECS/UI/Components/TextureComponent')
local TweenComponent = require('leviathan/ECS/UI/Components/TweenComponent')
local UIHoverSystem = require('leviathan/ECS/UI/Systems/HoverSystem')
local UIInputSystem = require('leviathan/ECS/UI/Systems/InputSystem')
local UIRenderSystem = require('leviathan/ECS/UI/Systems/RenderSystem')
local UITweenSystem = require('leviathan/ECS/UI/Systems/TweenSystem')

local DomainMainMenu = Domain:derive('MainMenu')

function DomainMainMenu:new(world)
    -- call parent constructor
    DomainMainMenu.super.new(self, world, 'MainMenu')
    -- screen dimensions
    local screenW, screenH = love.window.getMode()
    -- get managers
    local ImagesManager = world:getManager('ImagesManager')
    local FontsManager = world:getManager('FontsManager')
    -- menu
    local menuItems = 5 -- 4 menu items + 1 period
    -- cover
    local coverTexture = ImagesManager:getImageTexture('OldRustyMetal')
    local coverW = math.floor(screenW * 0.33)
    local coverH = math.floor(coverW * (coverTexture.h / coverTexture.w))
    local menuItemH = math.floor(coverH / (menuItems + 0.65))
    -- cover positions
    local yStart = coverH * -1.2
    local yFinish = coverH * 0.2
    -- font
    local menuFontSize = coverH * 0.2 -- 20% of cover height
    local font = FontsManager:getFont('HandWriteScratch', menuFontSize)

    -- set buffer size
    self.buffer.worldX = math.floor(screenW * 0.65)
    self.buffer.worldY = math.floor(-1.2 * coverH)
    self.buffer.w = coverW
    self.buffer.h = coverH

    local text, y, hh, hd
    -- main cover
    local cover = Entity(self, 'MainMenuCover', 0, 0, coverW, coverH)
    local coverTextureComp = TextureComponent(coverTexture.texture, 0, 0, coverW, coverH, 'center', 'center', true, 0.5)
    cover:addComponent(coverTextureComp)
    -- button highlight image
    local bHighTexture = ImagesManager:getImageTexture('PaintStroke')
    hh = 1.5 * menuItemH -- height of highlight texture
    hd = -0.25 * menuItemH -- displace of highlight texture to fit item
    -- button Start Game normal
    text = i18n.translate('StartGame')
    y = menuItemH * 0.5
    local bStartNorm = Entity(self, 'bStartNorm', 0, y, coverW, menuItemH)
    local bStartTextNorm = TextComponent('bStartTextNorm', 0, 0, coverW, menuItemH, text, font, Color.black, 'center')
    bStartNorm:addComponent(bStartTextNorm)
    cover:addChild(bStartNorm)
    -- button Start Game high
    local bStartHigh = Entity(self, 'bStartHigh', 0, y, coverW, menuItemH)
    local bStartTextureComp = TextureComponent(bHighTexture.texture, 0, hd, coverW, hh, 'center', 'bottom', false)
    bStartHigh:addComponent(bStartTextureComp)
    local bStartTextHigh = TextComponent('bStartTextHigh', 0, 0, coverW, menuItemH, text, font, Color.white, 'center')
    bStartHigh:addComponent(bStartTextHigh)
    cover:addChild(bStartHigh)
    bStartHigh:setPriority(700)
    bStartTextureComp.priority = 550
    bStartHigh.enabled = false
    -- button Start Game
    local bStart = Entity(self, 'bStart', 0, y, coverW, menuItemH)
    local bStartHoverComp = MouseHoverComponent(self.buttonStartHoverOn, self.buttonStartHoverOff)
    bStart:addComponent(bStartHoverComp)
    local bStartClickComponent = MouseClickComponent(self.buttonStartClick, 'MouseLeftButton', 'ButtonAsyncPressedComponent')
    bStart:addComponent(bStartClickComponent)
    cover:addChild(bStart)
    -- button Options normal
    text = i18n.translate('Options')
    y = menuItemH * 1.75
    local bOptionsNorm = Entity(self, 'bOptionsNorm', 0, y, coverW, menuItemH)
    local bOptTextNorm = TextComponent('bOptionsTextNorm', 0, 0, coverW, menuItemH, text, font, Color.black, 'center')
    bOptionsNorm:addComponent(bOptTextNorm)
    cover:addChild(bOptionsNorm)
    -- button Options high
    local bOptionsHigh = Entity(self, 'bOptionsHigh', 0, y, coverW, menuItemH)
    local bOptionsTextureComp = TextureComponent(bHighTexture.texture, 0, hd, coverW, hh, 'center', 'bottom', false)
    bOptionsHigh:addComponent(bOptionsTextureComp)
    local bOptTextHigh = TextComponent('bOptionsTextHigh', 0, 0, coverW, menuItemH, text, font, Color.white, 'center')
    bOptionsHigh:addComponent(bOptTextHigh)
    cover:addChild(bOptionsHigh)
    bOptionsHigh:setPriority(700)
    bOptionsTextureComp.priority = 550
    bOptionsHigh.enabled = false
    -- button Options
    local bOptions = Entity(self, 'bOptions', 0, y, coverW, menuItemH)
    local bOptionsHoverComp = MouseHoverComponent(self.buttonOptionsHoverOn, self.buttonOptionsHoverOff)
    bOptions:addComponent(bOptionsHoverComp)
    local bOptionsClickComponent = MouseClickComponent(self.buttonOptionsClick, 'MouseLeftButton', 'ButtonAsyncPressedComponent')
    bOptions:addComponent(bOptionsClickComponent)
    cover:addChild(bOptions)
    -- button About normal
    text = i18n.translate('About')
    y = menuItemH * 3
    local bAboutNorm = Entity(self, 'bAboutNorm', 0, y, coverW, menuItemH)
    local bAboutTextNorm = TextComponent('bAboutTextNorm', 0, 0, coverW, menuItemH, text, font, Color.black, 'center')
    bAboutNorm:addComponent(bAboutTextNorm)
    cover:addChild(bAboutNorm)
    -- button About high
    local bAboutHigh = Entity(self, 'bAboutHigh', 0, y, coverW, menuItemH)
    local bAboutTextureComp = TextureComponent(bHighTexture.texture, 0, hd, coverW, hh, 'center', 'bottom', false)
    bAboutHigh:addComponent(bAboutTextureComp)
    local bAboutTextHigh = TextComponent('bAboutTextHigh', 0, 0, coverW, menuItemH, text, font, Color.white, 'center')
    bAboutHigh:addComponent(bAboutTextHigh)
    cover:addChild(bAboutHigh)
    bAboutHigh:setPriority(700)
    bAboutTextureComp.priority = 550
    bAboutHigh.enabled = false
    -- button About
    local bAbout = Entity(self, 'bAbout', 0, y, coverW, menuItemH)
    local bAboutHoverComp = MouseHoverComponent(self.buttonAboutHoverOn, self.buttonAboutHoverOff)
    bAbout:addComponent(bAboutHoverComp)
    local bAboutClickComponent = MouseClickComponent(self.buttonAboutClick, 'MouseLeftButton', 'ButtonAsyncPressedComponent')
    bAbout:addComponent(bAboutClickComponent)
    cover:addChild(bAbout)
    -- button Quit normal
    text = i18n.translate('QuitGame')
    y = menuItemH * 4.25
    local bQuitNorm = Entity(self, 'bQuitNorm', 0, y, coverW, menuItemH)
    local bQuitTextNorm = TextComponent('bQuitTextNorm', 0, 0, coverW, menuItemH, text, font, Color.black, 'center')
    bQuitNorm:addComponent(bQuitTextNorm)
    cover:addChild(bQuitNorm)
    -- button Quit high
    local bQuitHigh = Entity(self, 'bQuitHigh', 0, y, coverW, menuItemH)
    local bQuitTextureComp = TextureComponent(bHighTexture.texture, 0, hd, coverW, hh, 'center', 'bottom', false)
    bQuitHigh:addComponent(bQuitTextureComp)
    local bQuitTextHigh = TextComponent('bQuitTextHigh', 0, 0, coverW, menuItemH, text, font, Color.white, 'center')
    bQuitHigh:addComponent(bQuitTextHigh)
    cover:addChild(bQuitHigh)
    bQuitHigh:setPriority(700)
    bQuitTextureComp.priority = 550
    bQuitHigh.enabled = false
    -- button Quit
    local bQuit = Entity(self, 'bQuit', 0, y, coverW, menuItemH)
    local bQuitHoverComp = MouseHoverComponent(self.buttonQuitHoverOn, self.buttonQuitHoverOff)
    bQuit:addComponent(bQuitHoverComp)
    local bQuitClickComponent = MouseClickComponent(self.buttonQuitClick, 'MouseLeftButton', 'ButtonAsyncPressedComponent')
    bQuit:addComponent(bQuitClickComponent)
    cover:addChild(bQuit)
    -- entity: TweenIn
    local tweenIn = Entity(self, 'TweenIn', 0, 0, 0, 0)
    tweenIn.enabled = false
    local tweenInComp = TweenComponent(2.0, self.buffer, {worldY = yFinish}, 'inOutCubic')
    tweenIn:addComponent(tweenInComp)
    -- entity: TweenOut
    local tweenOut = Entity(self, 'TweenOut', 0, 0, 0, 0)
    tweenOut.enabled = false
    local tweenOutComp = TweenComponent(2.0, self.buffer, {worldY = yStart}, 'inOutCubic')
    tweenOut:addComponent(tweenOutComp)
    -- systems
    local hover = UIHoverSystem(self)
    local input = UIInputSystem(self)
    local render = UIRenderSystem(self)
    local tween = UITweenSystem(self)
    -- adding systems
    DomainMainMenu:addSystem(self, hover)
    DomainMainMenu:addSystem(self, input)
    DomainMainMenu:addSystem(self, render)
    DomainMainMenu:addSystem(self, tween)
end

function DomainMainMenu:onEnter(from)
    world:getDomain('MainMenuBackground')
    DomainMainMenu:slideIn()
end

function DomainMainMenu:onExit()
    DomainMainMenu:slideOut()
end

-- buttons hover

function DomainMainMenu:buttonStartHoverOn()
    local domain = self.entity.domain
    domain:getEntity('bStartNorm').enabled = false
    domain:getEntity('bStartHigh').enabled = true
    domain.changed = true
end

function DomainMainMenu:buttonStartHoverOff()
    local domain = self.entity.domain
    domain:getEntity('bStartNorm').enabled = true
    domain:getEntity('bStartHigh').enabled = false
    domain.changed = true
end

function DomainMainMenu:buttonOptionsHoverOn()
    local domain = self.entity.domain
    domain:getEntity('bOptionsNorm').enabled = false
    domain:getEntity('bOptionsHigh').enabled = true
    domain.changed = true
end

function DomainMainMenu:buttonOptionsHoverOff()
    local domain = self.entity.domain
    domain:getEntity('bOptionsNorm').enabled = true
    domain:getEntity('bOptionsHigh').enabled = false
    domain.changed = true
end

function DomainMainMenu:buttonAboutHoverOn()
    local domain = self.entity.domain
    domain:getEntity('bAboutNorm').enabled = false
    domain:getEntity('bAboutHigh').enabled = true
    domain.changed = true
end

function DomainMainMenu:buttonAboutHoverOff()
    local domain = self.entity.domain
    domain:getEntity('bAboutNorm').enabled = true
    domain:getEntity('bAboutHigh').enabled = false
    domain.changed = true
end

function DomainMainMenu:buttonQuitHoverOn()
    local domain = self.entity.domain
    domain:getEntity('bQuitNorm').enabled = false
    domain:getEntity('bQuitHigh').enabled = true
    domain.changed = true
end

function DomainMainMenu:buttonQuitHoverOff()
    local domain = self.entity.domain
    domain:getEntity('bQuitNorm').enabled = true
    domain:getEntity('bQuitHigh').enabled = false
    domain.changed = true
end

-- buttons click

function DomainMainMenu:buttonStartClick(button)
    -- sound click
    local audio = world:getDomain('Audio')
    audio:stopMusic()
    audio:playSound('accept')
    -- walk to Prologue
    Log:debug('[MainMenu] [MainMenu] => [Prologue]')
    world:deleteDomain('MainMenuBackground')
    world:switchDomain(self, 'prologue_001')
end

function DomainMainMenu:buttonOptionsClick(domain, button)
    -- sound click
    local audio = world:getDomain('Audio')
    audio:playSound('accept')
    -- walk to Options
    Log:debug('[MainMenu] [MainMenu] => [Options]')
end

function DomainMainMenu:buttonAboutClick(domain, button)
    -- sound click
    local audio = world:getDomain('Audio')
    audio:playSound('accept')
    -- walk to About
    Log:debug('[MainMenu] [MainMenu] => [About]')
    local about = world:getDomain('About')
    world:switchDomain(self, 'About', true)
end

function DomainMainMenu:buttonQuitClick(domain, button)
    Log:debug('[MainMenu] [MainMenu] => [Quit]')
    love.event.quit(0)
end

function DomainMainMenu:slideIn()
    local domain = world:getDomain('MainMenu')
    local entityIn = domain:getEntity('TweenIn')
    local comp = entityIn:getComponent('TweenComponent')
    comp.tween:reset()
    entityIn.enabled = true
    local entityOut = domain:getEntity('TweenOut')
    entityOut.enabled = false
end

function DomainMainMenu:slideOut()
    local domain = world:getDomain('MainMenu')
    local entityIn = domain:getEntity('TweenIn')
    entityIn.enabled = false
    local entityOut = domain:getEntity('TweenOut')
    local comp = entityOut:getComponent('TweenComponent')
    comp.tween:reset()
    entityOut.enabled = true
end

return DomainMainMenu
